/*
 * Copyright 2007 www.luzand.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


var yrprxHTMLContentHelper = {};

yrprxHTMLContentHelper.containsElement = function(doc, tagName, functor)
{
    if (!doc)
        return false;

    try
    {
        var elems = doc.getElementsByTagName(tagName);
        if (!functor)
        {
            if (elems.length > 0)
                return true;
        }
        else
        {
            for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
                if (functor(elems[i]))
                    return true;
        }
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - containsElement: Exception: " + ex + "\n");
    }

    try
    {
        var iframes = doc.getElementsByTagName('iframe');
        for (var j = 0, numOfIFrames = iframes.length; j < numOfIFrames; ++j)
            if (this.containsElement(iframes[j].contentDocument, tagName, functor))
                return true;
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - containsElement: Exception: " + ex + "\n");
    }

    try
    {
        var frames = doc.getElementsByTagName('frame');
        for (var f = 0, numOfFrames = frames.length; f < numOfFrames; ++f)
            if (this.containsElement(frames[f].contentDocument, tagName, functor))
                return true;
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - containsElement: Exception: " + ex + "\n");
    }

    return false;
}

yrprxHTMLContentHelper.hasParentWithId = function (elem, parentId)
{
    if (!elem)
        return false;

    for (var parent = elem.parentNode; parent; parent = parent.parentNode)
        if (parent.id == parentId)
            return true;

    return false;
}

yrprxHTMLContentHelper.getParentWithTag = function (elem, tagName)
{
    if (!elem)
        return null;

    for (var parent = elem.parentNode; parent; parent = parent.parentNode)
        if (parent.tagName == tagName)
            return parent;

    return null;
}

yrprxHTMLContentHelper.enumerateElementsByTagName = function(doc, tagName, handler)
{
    if (!doc || !tagName || !handler)
        return;

    try
    {
        var elems = doc.getElementsByTagName(tagName);
        for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
            handler(elems[i]);
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - enumerateElementsByTagName: Exception: " + ex + "\n");
    }

    try
    {
        var iframes = doc.getElementsByTagName('iframe');
        for (var j = 0, numOfIFrames = iframes.length; j < numOfIFrames; ++j)
        {
            this.enumerateElementsByTagName(iframes[j].contentDocument, tagName, handler);
        }
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - enumerateElementsByTagName: Exception: " + ex + "\n");
    }

    try
    {
        var frames = doc.getElementsByTagName('frame');
        for (var f = 0, numOfFrames = frames.length; f < numOfFrames; ++f)
        {
            this.enumerateElementsByTagName(frames[f].contentDocument, tagName, handler);
        }
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - enumerateElementsByTagName: Exception: " + ex + "\n");
    }
}

yrprxHTMLContentHelper.enumerateChildElements = function(elem, handler, arg1, arg2, arg3)
{
    if (!elem || !handler)
        return;

    try
    {
        var elems = elem.childNodes;

        for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
            handler(elems[i], arg1, arg2, arg3);
    }
    catch(ex)
    {
        dump("ERROR yrprxHTMLContentHelper - enumerateChildElements: Exception: " + ex + "\n");
    }
}

yrprxHTMLContentHelper.getAllElementsByTagName = function(doc, tagName, functor)
{
    var result = new Array();

    if (!functor)
    {
        this.enumerateElementsByTagName(doc, tagName, function(elem) {
            result[result.length] = elem;
        });
    }
    else
    {
        this.enumerateElementsByTagName(doc, tagName, function(elem) {
            var value = functor(elem);
            if (value) // skip NULLs
                result[result.length] = value;
        });
    }

    return result;
}

/**
 * HTMLContentHelperSaveImageProgressListener
 */
function yrprxHTMLContentHelperSaveImageProgressListener(onCompleteCallback)
{
    this.logger = yrprxFactory.createLogger("yrprxHTMLContentHelperSaveImageProgressListener");

    this.onCompleteCallback = onCompleteCallback;
}

yrprxHTMLContentHelperSaveImageProgressListener.prototype = {
    QueryInterface: function(aIID)
    {
        if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
            aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
            aIID.equals(Components.interfaces.nsISupports))
            return this;

        throw Components.results.NS_NOINTERFACE;
    },
    onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus)
    {
        if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START)
        {
            this.logger.debug("onStateChange: start");
        }
        if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
        {
            this.logger.debug("onStateChange: stop");
            try
            {
                if (!this.onCompleteCallback)
                    return;

                this.logger.debug("onStateChange: do callback");
                this.onCompleteCallback();
            }
            catch(ex)
            {
                if (this.logger.enabled) this.logger.error("onStateChange: Exception: " + ex);
            }
        }
        return 0;
    },
    onLocationChange: function(aProgress, aRequest, aURI)
    {
        this.logger.debug("onLocationChange");
        return 0;
    },
    onProgressChange : function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress){
        if (this.logger.enabled) this.logger.debug("onProgressChange: curSelfProgress=" + aCurSelfProgress + ", maxSelfProgress=" + aMaxSelfProgress + ", curTotalProgress="+ aCurTotalProgress +", maxTotalProgress="+ aMaxTotalProgress);
        return 0;
    },
    onSecurityChange : function (aWebProgress, aRequest, state){
        this.logger.debug("onSecurityChange");
        return 0;
    },
    onStatusChange : function (aWebProgress, aRequest, aStatus, aMessage){
        if (this.logger.enabled) this.logger.debug("onStatusChange: " + aMessage);
        return 0;
    }
}

/**
 * Try to save image by URL to destination file.
 *
 * @param srcURL              string URL
 * @param destFile            nsIFile instance
 * @param onCompleteCallback  callback on complete
 * @param flags               persist flags (can be undefined, default: PERSIST_FLAGS_FROM_CACHE|PERSIST_FLAGS_CLEANUP_ON_FAILURE)
 */
yrprxHTMLContentHelper.saveImage = function(srcURL, destFile, onCompleteCallback, flags)
{
    var uriFixup = yrprxComponentsFactory.getURIFixupService();

    var uri = uriFixup.createFixupURI(srcURL, 0);
    var host = (uri.host.length > 0) ? uriFixup.createFixupURI(uri.host, 0) : null;

    var persist = yrprxComponentsFactory.createWebBrowserPersist();

    persist.persistFlags = (typeof flags != 'undefined') ? flags : Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE | Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_CLEANUP_ON_FAILURE;
    persist.progressListener = new yrprxHTMLContentHelperSaveImageProgressListener(onCompleteCallback);

    persist.saveURI(uri, null, host, null, null, destFile);
}
